﻿//-----------------------------------------------------------------------
// <copyright file="XmlLogProvider.cs" company="Anthony Steele">
// This source forms part of the DuplicateFinder utility
// Hosted at http://www.codeplex.com/DuplicateFinder
//
// logging code by John Miller
// This source is available under the terms of the Microsoft Public License (Ms-PL)
// See http://duplicatefinder.codeplex.com/license
// All other rights reserved.
// </copyright>
//-----------------------------------------------------------------------

namespace DupFinder.Logging
{
    using System;
    using System.Globalization;
    using System.Xml;

    using DuplicateFinderLib;

    /// <summary>
    /// This class logs the output to an Xml file
    /// </summary>
    public class XmlLogProvider : ILogProvider
    {
        /// <summary>
        /// XmlDocument that is built for logging purposes
        /// </summary>
        private readonly XmlDocument logFile;

        /// <summary>
        /// Name of file to save report as
        /// </summary>
        private readonly string fileName;

        private readonly bool consoleMode;

        /// <summary>
        /// Initializes a new instance of the XmlLogProvider class.
        /// </summary>
        /// <param name="fileName">the file to write to</param>
        public XmlLogProvider(string fileName)
        {
            this.logFile = new XmlDocument();
            XmlElement documentRoot = this.logFile.CreateElement("DuplicateReport");
            this.logFile.PrependChild(documentRoot);

            this.fileName = fileName;
            this.consoleMode = (string.Equals("console", fileName, StringComparison.OrdinalIgnoreCase));            
        }

        /// <summary>
        /// Logs a message to the Xml File
        /// </summary>
        /// <param name="message">message to be saved in the logs</param>
        public void LogMessage(string message)
        {
            XmlNode messageNode = this.logFile.CreateElement("Message");
            messageNode.InnerText = message;
            this.logFile.DocumentElement.AppendChild(messageNode);
        }

        /// <summary>
        /// This logs a duplicate with the filename and line numbers
        /// </summary>
        /// <param name="e">DuplicateEventArg with duplication information</param>
        public void LogDuplication(DuplicateEventArgs e)
        {
            XmlElement messageNode = this.logFile.CreateElement("Duplicates");
            messageNode.SetAttribute("Length", e.Length.ToString(CultureInfo.InvariantCulture));
            foreach (LineItem item in e.Items)
            {
                XmlElement dup = this.logFile.CreateElement("Duplicate");
                dup.SetAttribute("FileName", item.FileName);
                dup.SetAttribute("LineNumber", item.LineNumber.ToString(CultureInfo.InvariantCulture));
                messageNode.AppendChild(dup);
            }

            this.logFile.DocumentElement.AppendChild(messageNode);
        }

        /// <summary>
        /// This logs the number of files that were analyzed
        /// </summary>
        /// <param name="fileCount">number of files processed</param>
        public void LogFileCount(int fileCount)
        {
            this.logFile.DocumentElement.SetAttribute("FileCount", fileCount.ToString(CultureInfo.InvariantCulture));
        }

        /// <summary>
        /// This logs the total number of duplications found.
        /// </summary>
        /// <param name="duplicateCount">the number of duplicate items found</param>
        public void LogDuplicateCount(int duplicateCount)
        {
            this.logFile.DocumentElement.SetAttribute("DuplicateCount", duplicateCount.ToString(CultureInfo.InvariantCulture));
        }

        /// <summary>
        /// This saves the report to disk
        /// </summary>
        public void Close()
        {
            XmlTextWriter writer;

            if (this.consoleMode)
            {
                writer = new XmlTextWriter(Console.Out);
            }
            else
            {
                writer = new XmlTextWriter(this.fileName, null);                
            }

            this.logFile.WriteContentTo(writer);
            writer.Close();
        }
    }
}
